#include <math.h>
#include <sekai/JSONReader.h>
#include <sekai/OLABuffer.h>
#include <sekai/common.h>
#include <sndfile.h>

void window(float *wav, int length) {
  int i;
  for (i = 0; i < length; i++) {
    wav[i] =
        wav[i] *
        (0.5 - 0.5 * cos(2.0 * M_PI * (float)(i + 1) / ((float)(length + 1))));
  }
}

SNDFILE *openOutFile(int samplerate) {
  SF_INFO info;
  memset(&info, 0, sizeof(info));
  info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
  info.samplerate = samplerate;
  info.channels = 1;
  return sf_open("output.wav", SFM_WRITE, &info);
}

int main() {
  JSONReader json;
  json.readFile("test.json");

  OLABuffer ola(16 * 1024);

  float currentTime = 0;
  float currentIndex = 0;

  int samplerate = json.getSamplerate();

  printf("samplerate %i\n", samplerate);

  float f0 = json.getPitch();
  int T0 = (int)((samplerate / f0) + 0.5);

  printf("f0 %f\n", f0);

  float new_f0 = 440;
  int new_T0 = (int)((samplerate / new_f0) + 0.5);

  float y_end = json.getLength();

  float *buffer = new float[T0 * 2];
  float *buffera = new float[T0 * 2];
  float *bufferb = new float[T0 * 2];

  int outbuf_len = 1024;
  float *outbuf = new float[outbuf_len];

  float x[2] = {0, 10.0};
  float y[2] = {0, y_end};
  int n = 2;

  float x_end = x[n - 1];

  SNDFILE *sf = openOutFile(samplerate);

  while (currentTime < x_end) {
    currentIndex = ola.currentTime();  // rename to currentIndex
    currentTime = currentIndex / samplerate;

    if (currentTime >= x_end) break;

    float pos = interp_linear(x, y, n, currentTime);

    memset(bufferb, 0, sizeof(float) * T0 * 2);
    memset(buffera, 0, sizeof(float) * T0 * 2);
    float interp;
    bool result = json.copyIn(buffera, bufferb, &interp, T0 * 2, pos);
    for (int i = 0; i < T0 * 2; i++) {
      buffer[i] = buffera[i] * (1 - interp) + bufferb[i] * interp;
    }
    window(buffer, T0 * 2);

    ola.ola(buffer, T0 * 2, new_T0);
    while (ola.isFilled(outbuf_len * 4)) {
      ola.pop(outbuf, outbuf_len);
      sf_write_float(sf, outbuf, outbuf_len);
    }
  }
  sf_close(sf);
}
